package com.ruoyi.back.service.impl

import cn.hutool.core.bean.BeanUtil
import cn.hutool.core.date.DateUtil
import cn.hutool.core.util.RandomUtil
import cn.hutool.core.util.StrUtil
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import com.baomidou.shaun.core.context.ProfileHolder
import com.ruoyi.app.common.*
import com.ruoyi.back.domain.UserMember
import com.ruoyi.back.domain.UserMemberOrder
import com.ruoyi.back.domain.dto.UserMemberOrderDto
import com.ruoyi.back.domain.dto.UserMemberOrderSearchDto
import com.ruoyi.back.domain.vo.PayRecordVo
import com.ruoyi.back.domain.vo.UserMemberOrderDetailVo
import com.ruoyi.back.domain.vo.UserMemberOrderListVo
import com.ruoyi.back.enums.PayStatusEnum
import com.ruoyi.back.enums.PayTypeEnum
import com.ruoyi.back.enums.UserTypeEnum
import com.ruoyi.back.mapper.UserMemberOrderMapper
import com.ruoyi.back.service.AppUserService
import com.ruoyi.back.service.MemberService
import com.ruoyi.back.service.UserMemberOrderService
import com.ruoyi.back.service.UserMemberService
import com.ruoyi.common.core.page.PageDomain
import com.ruoyi.common.core.page.TableSupport
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.sql.Struct

@Service
class UserMemberOrderServiceImpl : ServiceImpl<UserMemberOrderMapper, UserMemberOrder>(), UserMemberOrderService {

    @Autowired
    private lateinit var memberService: MemberService

    @Autowired
    private lateinit var appUserService: AppUserService

    @Autowired
    private lateinit var userMemberService: UserMemberService

    @Autowired
    private lateinit var userService: AppUserService

    override fun createUserMemberOrder(userMemberOrderDto: UserMemberOrderDto): UserMemberOrder =
        UserMemberOrder().apply {
            BeanUtil.copyProperties(userMemberOrderDto, this)
            orderNum = "${DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss")}${RandomUtil.randomNumbers(8)}"
            userService.getById(ProfileHolder.getProfile().id)?.let { appUser ->
                userId = appUser.userId
                username = appUser.username
                createBy = appUser.id
            }
            payAmount = memberService.getById(userMemberOrderDto.memberId)?.price
        }.also { save(it) }

    override fun payRecordList(userId: Long, pageDomain: PageDomain): Page<PayRecordVo> =
        page(
            Page(pageDomain.pageNum.toLong(), pageDomain.pageSize.toLong()), KtQueryWrapper(UserMemberOrder::class.java)
                .eq(UserMemberOrder::createBy, userId)
                .eq(UserMemberOrder::payStatus, PayStatusEnum.PAY_SUCCESS.code)
                .orderByDesc(UserMemberOrder::payDate)
        )
            .let { page: Page<UserMemberOrder> ->

                Page<PayRecordVo>().apply {
                    BeanUtil.copyProperties(page, this)
                    records = page.records.takeIf { it.isNotEmpty() }
                        ?.run {
                            map {
                                PayRecordVo().apply {
                                    BeanUtil.copyProperties(it, this)
                                    memberName = memberService.getNameByMemberId(it.memberId!!)
                                }
                            }
                        }
                }
            }

    override fun getUserMemberOrderByOrderNum(orderNum: String): UserMemberOrder? =
        getOne(KtQueryWrapper(UserMemberOrder::class.java).eq(UserMemberOrder::orderNum, orderNum))

    override fun userMemberOrderPage(userMemberOrderSearchDto: UserMemberOrderSearchDto): Page<UserMemberOrderListVo> =
        TableSupport.buildPageRequest().let { pageDomain ->

            //更新是否过期状态
            page(
                Page(pageDomain.pageNum.toLong(), pageDomain.pageSize.toLong()),
                KtQueryWrapper(UserMemberOrder::class.java).eq(
                    UserMemberOrder::payStatus,
                    PayStatusEnum.PAY_SUCCESS.code
                )
            ).let { page: Page<UserMemberOrder> ->
                page.records.takeIf { it.isNotEmpty() }
                    ?.run {
                        forEach { order ->
                           DateUtil.date().takeIf { it gt order.expireDate!! }
                               ?.run {
                                   updateById(order.apply {
                                       expire = true
                                   })
                               }
                        }
                    }
            }


            page(
                Page(pageDomain.pageNum.toLong(), pageDomain.pageSize.toLong()),
                KtQueryWrapper(UserMemberOrder::class.java).apply {
                    eq(UserMemberOrder::payStatus, PayStatusEnum.PAY_SUCCESS.code)
                    userMemberOrderSearchDto.searchParam?.let { searchParam ->
                        eq(UserMemberOrder::orderNum, searchParam).or().eq(UserMemberOrder::userId, searchParam).or()
                            .eq(UserMemberOrder::username, searchParam)
                    }
                    gt(StrUtil.isNotBlank(userMemberOrderSearchDto.payDateBeginDate), UserMemberOrder::payDate, userMemberOrderSearchDto.payDateBeginDate.date())
                    lt(StrUtil.isNotBlank(userMemberOrderSearchDto.payDateEndDate), UserMemberOrder::payDate, userMemberOrderSearchDto.payDateEndDate.date())
                    userMemberOrderSearchDto.expire?.let { expire ->
                        eq(UserMemberOrder::expire, expire)
                    }
                    userMemberOrderSearchDto.channel?.let { channel ->
                        eq(UserMemberOrder::channel, channel)
                    }
                    orderByDesc(UserMemberOrder::payDate)
                }).let { page: Page<UserMemberOrder> ->

                Page<UserMemberOrderListVo>().apply {
                    BeanUtil.copyProperties(page, this)
                    records = page.records.takeIf { it.isNotEmpty() }?.run {
                        map {
                            UserMemberOrderListVo().apply {
                                BeanUtil.copyProperties(it, this)
                                payType = it.payType?.payType()
                                expire = when (it.expire) {
                                    true -> "已到期"
                                    false -> "未到期"
                                    null -> "未知"
                                }
                                payDate = it.payDate?.format()
                                expireDate = it.expireDate?.format()
                                validityPeriod = memberService.getById(it.memberId)?.run { if (period != 0) "${period}${periodUnit?.unitType()}" else "永久" }
                            }
                        }
                    }
                }
            }
        }

    override fun userMemberOrderDetail(orderId: Long): Data<UserMemberOrderDetailVo> =
        getById(orderId)?.let { order ->
            Ok("获取订单详情成功", UserMemberOrderDetailVo().apply {
                userInfo = appUserService.appUserInfo(order.createBy!!)
                BeanUtil.copyProperties(order, this)
                payType = order.payType?.payType()
                expire = when (order.expire) {
                    true -> "已到期"
                    false -> "未到期"
                    null -> "未知"
                }
                payDate = order.payDate?.format()
                expireDate = order.expireDate?.format()
                validityPeriod = memberService.getById(order.memberId)?.run { "${period}${periodUnit?.unitType()}" }
            })
        } ?: Fail(201, "不存在当前订单")

    override fun removeMemberOrder(orderId: Long): Data<Boolean> =
        getById(orderId)?.run {
            Ok("移除成功", removeById(orderId))
        } ?: Fail(201, "不存在当前资源")

    override fun updateMemberPayStatus(orderNum: String, payTypeEnum: PayTypeEnum) {
        getOne(
            KtQueryWrapper(UserMemberOrder::class.java)
                .eq(UserMemberOrder::orderNum, orderNum)
                .eq(UserMemberOrder::payType, payTypeEnum.code)
        )
            ?.let {

                userMemberService.getUserMemberByUserId(it.createBy!!)
                    ?.run {
                        userMemberService.updateById(this.apply {
                            endMemberDate = DateUtil.offsetDay(endMemberDate, memberService.memberDay(it.memberId!!) ?: 0)

                            appUserService.updateById(appUserService.getById(it.createBy)?.run {
                                apply {
                                    userType = UserTypeEnum.MEMBER.code
                                }
                            })
                            updateById(it.apply {
                                expireDate = endMemberDate
                                payDate = DateUtil.date()
                                memberType = memberService.getById(it.memberId)?.name
                                payStatus = PayStatusEnum.PAY_SUCCESS.code
                            })
                        })
                    }
                    ?: kotlin.run {
                        userMemberService.save(UserMember().apply {
                            createBy = it.createBy
                            beginMemberDate = DateUtil.date()
                            endMemberDate = DateUtil.offsetDay(beginMemberDate, memberService.memberDay(it.memberId!!) ?: 0)
                            appUserService.updateById(appUserService.getById(it.createBy)?.run {
                                apply {
                                    userType = UserTypeEnum.MEMBER.code
                                }
                            })
                            updateById(it.apply {
                                expireDate = endMemberDate
                                payDate = DateUtil.date()
                                payStatus = PayStatusEnum.PAY_SUCCESS.code
                            })
                        })
                    }
            }
    }

    override fun getUserLastOrderName(userId: Long): String? =
        getOne(KtQueryWrapper(UserMemberOrder::class.java)
            .eq(UserMemberOrder::createBy, userId)
            .eq(UserMemberOrder::payStatus, PayStatusEnum.PAY_SUCCESS.code)
            .orderByDesc(UserMemberOrder::payDate)
            .last("limit 1"))
            ?.run {
                memberService.getById(memberId)?.name
            }
}